package org.acghub.mtdb.core;

import org.acghub.mtdb.common.exception.MtdbError;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class SavePoint {
    private final Map<Object, Log> logs = new HashMap<>();
    private final List<Log> addOrder = new ArrayList<Log>();
    private int access = 0;

    int commit() {
        for (Log log : addOrder) {
            log.commit();
        }
        return addOrder.size();
    }

    void rollback() {
        for (int i = addOrder.size() - 1; i >= 0; --i) {
            addOrder.get(i).rollback();
        }
    }

    boolean isAccessSince(int a) {
        return a != access;
    }

    int getAccess() {
        return access;
    }

    void access() {
        access++;
    }

    public <L extends Log> L get(LogKey key) {
        access();
        return (L) logs.get(key);
    }

    void add(Log log) {
        addOrder.add(log);
    }

    public void add(LogKey key, Log log) {
        access();
        Log old = logs.put(key, log);
        if (null != old) {
            logs.put(key, old);
            throw new MtdbError("impossible savepoint add duplicate log");
        }
        add(log);
    }

    void addIfAbsent(Object key, Log log) {
        access();
        if (logs.containsKey(key)) {
            return;
        }
        logs.put(key, log);
        add(log);
    }

    public void remove(LogKey key) {
        Log log = logs.remove(key);
        if (log != null) {
            addOrder.remove(log);
        }
    }
}
